#include <stddef.h>
#include <string.h>

#include "sprout.h"
#include "sprout_util.h"

char *c_object_to_json_object(const Object *obj)
{
    return c_to_json(obj, LEFT_BRACE, RIGHT_BRACE);
}

Object *json_object_to_c_object(const char **js)
{
    return json_to_c(js, LEFT_BRACE, RIGHT_BRACE);
}

char *c_array_to_json_array(const Array *arr)
{
    return c_to_json(arr, LEFT_BRACKET, RIGHT_BRACKET);
}

Array *json_array_to_c_array(const char **js)
{
    return json_to_c(js, LEFT_BRACKET, RIGHT_BRACKET);
}

char *c_string_to_json_string(const char *str)
{
    size_t len = strlen(str);
    char *result = (char *)allocate_memory(1 + len + 1 + 1);
    result[0] = DOUBLE_QUOTE;
    strcat(result, str);
    result[len + 1] = DOUBLE_QUOTE;
    result[len + 2] = NULL_CHARACTER;
    return result;
}

char *json_string_to_c_string(const char **js)
{
    skip_whitespace(js);
    if (**js == DOUBLE_QUOTE)
    {
        char *start, *end;
        start = end = (char *)(++*js);
        while (*end != DOUBLE_QUOTE)
        {
            end++;
        }
        if (*end == DOUBLE_QUOTE)
        {
            size_t len = end - start;
            char *result = (char *)allocate_memory(len + 1);
            for (size_t i = 0; i < len; i++)
            {
                result[i] = start[i];
            }
            result[len + 1] = NULL_CHARACTER;
            return result;
        }
    }
    return NULL;
}

void free_object(Object *obj)
{
    if (!obj)
    {
        return;
    }
    free_value(obj->value);
    free_memory(obj);
}

void free_array(Array *arr)
{
    free_object(arr);
}

void free_value(Value *v)
{
    if (!v)
    {
        return;
    }
    Value *curr;
    Value *next = v;
    do
    {
        curr = next;
        next = next->next;
        switch (curr->t)
        {
        case J_ARRAY:
            free_array(curr->v);
            break;
        case J_OBJECT:
            free_object(curr->v);
            break;
        }
        free_memory(curr);
    } while (next);
}

void free_string(char *v)
{
    free_memory(v);
}
